package vip.xumy.admin.um.conf;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import com.alibaba.fastjson.JSON;

import lombok.extern.log4j.Log4j2;
import vip.xumy.admin.um.service.IPermissionValidationService;
import vip.xumy.admin.utils.LoginUtil;
import vip.xumy.core.exception.CoreException;
import vip.xumy.core.pojo.com.AjaxResponse;
import vip.xumy.core.utils.StringUtil;

/**
 * 权限验证拦截器
 * 
 * @author mengyxu
 *
 */
@Log4j2
@Component
public class PermissionInteceptor implements HandlerInterceptor {
	@Autowired
	private IPermissionValidationService validationService;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
		log.debug("Permission interceptor : preHandle ...");
		response.setContentType("application/json;charset:UTF-8");
		// 获取此次请求需要的权限
		String path = request.getServletPath();
		try {
			verifyPath(path);

			// return if start with /public
			if (isPublicResource(path)) {
				return true;
			}

			List<String> resourceCodes = getResourceCodes(path);
			String userId = getLogonUser(request);

			// 判断用户是否拥有该权限
			getPermissionCode(userId, resourceCodes);

		} catch (CoreException e) {
			log.warn(e.getMessage());
			response.getWriter().write(JSON.toJSONString(new AjaxResponse(false, e.getMessage())));
			return false;
		}

		return true;
	}

	/**
	 * Lookup the login user from request/session.
	 * 
	 * @param request
	 * @return
	 * @throws CrsPermissionException if no "loginid" found.
	 */
	private String getLogonUser(HttpServletRequest request) throws CoreException {
		// 获取用户id
		String userName = LoginUtil.getUserNameAndRefresh(request);
		if (userName == null) {
			throw new CoreException("session timeout");
		}
		return userName;
	}

	/**
	 * Verify if it is null or empty.
	 * 
	 * @param path
	 * @throws CrsMvcException if path is null or empty.
	 */
	private void verifyPath(String path) throws CoreException {
		if (StringUtil.isEmpty(path)) {
			throw new CoreException("It is an empty request path");
		}
	}

	/**
	 * Search and return the resource codes by the resource content.
	 * 
	 * @param path
	 * @return
	 * @throws CrsPermissionException if no resource code found.
	 */
	private List<String> getResourceCodes(String path) throws CoreException {
		String resourcePath = path.substring(1);

		List<String> resCodes = validationService.queryCodeByContent(resourcePath);
		if (resCodes == null || resCodes.isEmpty()) {
			throw new CoreException("no permission for " + resourcePath);
		}

		return resCodes;
	}

	/**
	 * Verify if it an public resource.
	 * 
	 * @param path
	 * @return
	 */
	private boolean isPublicResource(String path) {
		return path.startsWith("/public");
	}

	/**
	 * Get the match resource code by user.
	 * 
	 * @param userId
	 * @param resCodes
	 * @return
	 * @throws CrsPermissionException if no resource code found.
	 */
	private String getPermissionCode(String userId, List<String> resCodes) throws CoreException {
		for (String resCode : resCodes) {
			if (validationService.havePermission(userId, resCode)) {
				return resCode;
			}
		}

		// No permission match.
		throw new CoreException("no permission");
	}
}
